/**
 * Wihidum - Efficient Broker Hierarchy for Publish Subscribe Middleware
 *
 * License      :   Apache License 2.0
 * Home Page    :   http://code.google.com/p/wihidum/
 * Mailing List :   wihidum@googlegroups.com
 */

package lk.mrt.cse.wihidum.subscriber.receiver;

import lk.mrt.cse.wihidum.subscriber.processor.GetPublicationsProcessor;
import lk.mrt.cse.wihidum.subscriber.processor.Processor;
import lk.mrt.cse.wihidum.subscriber.processor.SubscriptionProcessor;
import lk.mrt.cse.wihidum.util.WihidumConstants;
import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.soap.SOAPBody;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPFactory;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.receivers.AbstractInOutMessageReceiver;
import org.apache.log4j.Logger;

/**
 * Entry point of the messages received to the service
 */
public class MessageReceiver extends AbstractInOutMessageReceiver {

    private static final Logger logger = Logger.getLogger(MessageReceiver.class);
    private Processor subscriptionProcessor;
    private Processor getPublicationsProcessor;

    /**
     * Default contructor
     */
    public MessageReceiver() {
        getPublicationsProcessor = new GetPublicationsProcessor();
        subscriptionProcessor = new SubscriptionProcessor();
    }

    /**
     * Process the messages
     *
     * @param inMessage  Incoming message context
     * @param outMessage Outgoing message context
     * @throws AxisFault Exception
     */
    public void invokeBusinessLogic(MessageContext inMessage, MessageContext outMessage)
            throws AxisFault {
        //logger.info ("Subscriber service received a new message");

        try {
            // Get hold of the request SOAP Envelope
            SOAPEnvelope requestEnvelop = inMessage.getEnvelope();

            // Get the body element of request SOAP envelop
            SOAPBody requestEnvelopBody = requestEnvelop.getBody();

            //Get the actual request content element from SOAPBody
            OMElement messageElement = requestEnvelopBody.getFirstElement();

            //Get the header element of the content element
            OMElement requestHeaderElement = messageElement.getFirstElement();

            //Get the Action element which is the first element inside the header in all cases
            OMElement actionElement = requestHeaderElement.getFirstElement();

            //Get the action in order to delegate the processing of the request accordingly
            String action = actionElement.getText();

            // The response element
            OMElement responseElement;

            if (action.equals(WihidumConstants.Operations.SUBSCRIBE)) {
                logger.info("Received message to subscriber service is a subscription request");

                // Hand over the message to the subscription processor
                responseElement = subscriptionProcessor.processMessage(messageElement);

                // Set the response envelope in the response message context
                outMessage.setEnvelope(createResponse(responseElement));
            } else if (action.equals(WihidumConstants.Operations.GET_PUBLICATIONS)) {
                logger.info("Received message is a get publications request");

                // Hand over the message to the publication processor
                responseElement = getPublicationsProcessor.processMessage(messageElement);

                // Set the response envelope in the response message context
                outMessage.setEnvelope(createResponse(responseElement));
            } else {
                logger.info("Received message is in unrecognized format");
            }
        }
        catch (NullPointerException ex) {
            logger.error("Error in recognizing received message format", ex);
        }
        catch (OMException ex) {
            logger.error("Error in recognizing received message format", ex);
        }
        catch (AxisFault ex) {
            logger.error("Error in recognizing received message format", ex);
        }
    }

    /**
     * Create response SOAP envelop
     *
     * @param element Response element
     * @return Created response envelop
     */
    private SOAPEnvelope createResponse(OMElement element) {
        // Create the response SOAP facotry
        SOAPFactory factory = OMAbstractFactory.getSOAP11Factory();

        // Create the response SOAP envelop
        SOAPEnvelope responseEnvelop = factory.getDefaultEnvelope();

        // Add the response to the response SOAP envelop
        responseEnvelop.getBody().addChild(element);

        return responseEnvelop;
    }

    /**
     * Get publications processor setter method
     *
     * @param getPublicationsProcessor PublicationProcessor
     */
    public void setGetPublicationsProcessor(Processor getPublicationsProcessor) {
        this.getPublicationsProcessor = getPublicationsProcessor;
    }

    /**
     * Subscription processor setter method
     *
     * @param subscriptionProcessor SubscriptionProcessor
     */
    public void setSubscriptionProcessor(Processor subscriptionProcessor) {
        this.subscriptionProcessor = subscriptionProcessor;
    }

}
